package org.smoozik.services.musictheory;

import java.util.ArrayList;
import java.util.List;

import org.smoozik.app.ihm.Constants;

public class Scale {

	private List<Interval> listeIntervalles;
	private Note fondamentale;
	private int renversement;

	public Scale(Note note) {
		this.fondamentale = note;
		listeIntervalles = new ArrayList<>();
	}

	public Scale(Note note, Interval[] intervals) {
		this.fondamentale = note;
		addIntervals(intervals);
	}

	public int getRenversement() {
		return renversement;
	}

	public void setRenversement(int renversement) {
		this.renversement = renversement;
	}

	public String toString() {
		String lString = "";

		for (Note n : getNotes(0, this.listeIntervalles.size() - 1)) {
			lString += n + " ";
		}
		return lString;
	}

	public String toString2() {
		String lString = "";

		// notes printing
		ArrayList<Interval> relativeIntervalles = this.getRelativeIntervals();
		if (relativeIntervalles != null) {
			Note note = (Note) fondamentale;
			for (int i = 0; i < relativeIntervalles.size(); i++) {
				note = note.computeIntervalle(relativeIntervalles.get(i));
				lString += note.toString();
			}
		}
		return lString;
	}

	public Interval getTotalInterval() {
		Interval interval = null;

		if (fondamentale == null) {
			return null;
		}

		if (this.listeIntervalles != null) {
			for (int i = 0; i < this.listeIntervalles.size(); i++) {

				if (interval == null) {
					interval = new Interval(this.listeIntervalles.get(i));
				} else {
					interval.add(this.listeIntervalles.get(i));
				}
			}
		}

		return interval;
	}

	public Interval getStartInterval() {
		Interval interval = new Interval(Constants.UNISSON);

		if (fondamentale == null) {
			return null;
		}

		if (this.listeIntervalles != null) {
			for (int i = 0; i < this.renversement; i++) {
				interval.add(this.listeIntervalles.get(i));
			}
		}

		return interval;
	}

	public ArrayList<Interval> getRelativeIntervals() {
		ArrayList<Interval> lListe = new ArrayList<>();
//
//		// startInterval
//		lListe.add(getStartInterval());

		// intervals from renversement to end of list
		for (int i = renversement; i < this.listeIntervalles.size(); i++) {
			lListe.add(this.listeIntervalles.get(i));
		}

		if (renversement > 0) {
			// the revert of the total
//			Interval totalRevert = getTotalInterval();
//			totalRevert.revert();
//			lListe.add(totalRevert);

			// intervals from 0 to renversement-1
			for (int i = 0; i < renversement ; i++) {
				lListe.add(this.listeIntervalles.get(i));
			}
		}

		return lListe;
	}

	public void renversement(int nb) {
		setRenversement(nb);
	}

	public List<Interval> getListeIntervalles() {
		return listeIntervalles;
	}

	public void setListeIntervalles(List<Interval> listeIntervalles) {
		this.listeIntervalles = listeIntervalles;
	}

	public Note getFondamentale() {
		return fondamentale;
	}

	public void setFondamentale(Note fondamentale) {
		this.fondamentale = fondamentale;
	}

	public void addInterval(Interval interval) {
		if (this.listeIntervalles == null) {
			this.listeIntervalles = new ArrayList<>();
		}
		listeIntervalles.add(interval);
	}

	public void addIntervals(Interval[] interval) {
		if (this.listeIntervalles == null) {
			this.listeIntervalles = new ArrayList<>();
		}
		if (interval != null) {
			for (int i = 0; i < interval.length; i++) {
				listeIntervalles.add(interval[i]);
			}
		}
	}

	public Interval[] getIntervals() {
		Interval[] intervals = null;
		int i = 0;
		if (this.listeIntervalles != null) {
			intervals = new Interval[this.listeIntervalles.size()];
			for (Interval interval : listeIntervalles) {
				intervals[i] = interval;
				i++;
			}
		}
		return intervals;
	}

	public int getNbNotes() {
		int nbNotes = 0;
		if (this.fondamentale != null) {
			nbNotes = 1;
			if (this.listeIntervalles != null) {
				nbNotes += this.listeIntervalles.size();
			}
		}
		return nbNotes;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see AbstractFigure#getNotes()
	 */
	public ArrayList<Note> getNotes(int min, int max) {
		ArrayList<Note> lListe = new ArrayList<>();

		// notes printing
		Note note = (Note) fondamentale;
		int size = listeIntervalles.size();
		int index = 0;
		int nbOctave = 0;

		index = min % size;
		while(index < 0) {
			index += size;
			nbOctave --;
		}
		while(index > size) {
			index -= size;
			nbOctave ++;
		}
//		this.setRenversement(index);
		this.renversement = index;

		note = note.computeIntervalle(getStartInterval());
		while(nbOctave > 0) {
			note = note.computeIntervalle(Constants.OCTAVE);
			nbOctave--;
		}
		while(nbOctave < 0) {
			note = note.computeIntervalle(Constants.OCTAVE_INF);
			nbOctave++;
		}
		lListe.add(note);

		ArrayList<Interval> relativeIntervalles = getRelativeIntervals();
		for (int i = 0; i < max - min; i++) {
			index = i % size;
			note = note.computeIntervalle(relativeIntervalles.get(index));
			lListe.add(note);
		}

		return lListe;
	}

	public boolean equalsByInterval(Interval[] intervals1, Interval[] intervals2) {
		boolean result = true;

		if (intervals1 != null && intervals2 != null
				&& intervals2.length == intervals1.length) {
			for (int i = 0; i < intervals1.length; i++) {
				if (!intervals1[i].equals(intervals2[i])) {
					result = false;
					break;
				}
			}
		} else {
			result = false;
		}

		return result;
	}

}
